﻿using Bit.Art.Core;
using Bit.Art.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;

namespace Bit.Art.Distributed
{
    /// <summary>
    /// 放在redis分布式缓存中的订单索引
    /// </summary>
    [Serializable]
    public class MemCachedOrderIndex : ISerializable, IFixByteSerializable
    {
        public decimal Price { get; set; }

        public uint Side { get; set; }

        public ulong OrderId { get; set; }

        public int ByteSize => CUSTOM_SERIALIZE_SIZE;

        public MemCachedOrderIndex()
        {
        }

        public MemCachedOrderIndex(uint side, decimal price, ulong orderid)
        {
            Price = price;
            Side = side;
            OrderId = orderid;
        }

        #region ISerializable成员
        public MemCachedOrderIndex(SerializationInfo info, StreamingContext context)
        {
            OrderId = (ulong)info.GetValue("o", typeof(ulong));
            Price = (decimal)info.GetValue("p", typeof(decimal));
            Side = (uint)info.GetValue("s", typeof(uint));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("o", OrderId);
            info.AddValue("p", Price);
            info.AddValue("s", Side);
        }
        #endregion

        public const int CUSTOM_SERIALIZE_SIZE = 28;

        /// <summary>
        /// 将一个订单索引序列化成字节数组，采用自定义的序列化以节省空间
        /// </summary>
        /// <param name="item">要序列化的订单索引</param>
        /// <returns>序列化后的字节</returns>
        /// <remarks>
        /// 格式：
        /// 000 - 003: Side
        /// 004 - 011: OrderId
        /// 012 - 027: Price
        /// </remarks>
        public byte[] ToFixedBytes()
        {
            var bytes = new byte[CUSTOM_SERIALIZE_SIZE];

            // Side
            var serializedBytes = BitConverter.GetBytes(Side);
            Array.Copy(serializedBytes, 0, bytes, 0, 4);

            // OrderId
            serializedBytes = BitConverter.GetBytes(OrderId);
            Array.Copy(serializedBytes, 0, bytes, 4, 8);
            // Price
            Utility.Serialize(Price, bytes, 12);

            return bytes;
        }

        public static MemCachedOrderIndex FromBytes(byte[] bytes)
        {
            var item = new MemCachedOrderIndex(0, 0, 0);
            item.InitFrom(bytes);
            return item;
        }

        public void InitFrom(byte[] bytes)
        {
            // Side
            var serializedBytes = new byte[4];
            Array.Copy(bytes, 0, serializedBytes, 0, serializedBytes.Length);
            Side = BitConverter.ToUInt32(serializedBytes, 0);

            // OrderId
            serializedBytes = new byte[8];
            Array.Copy(bytes, 4, serializedBytes, 0, serializedBytes.Length);
            OrderId = BitConverter.ToUInt64(serializedBytes, 0);

            // Price
            Price = Utility.DecimalFromBytes(bytes, 12);
        }
    }
}
